/* Copyright (c) 2015,2016 Lucky Byte, Inc.
 */
package com.lucky_byte.pay.jar;

import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
 * 发送系统通知
 */
public class WebNotify
{
	private static final Logger logger = LogManager.getLogger();

	static public boolean notify(int level, String message) {
		sendNotifyMail(level, message);
		try {
			JdbcRecord record = new JdbcRecord();
			record.setField("sender", Runtime.getNotifySender());
			record.setField("level", level);
			record.setField("message", message);
			JdbcTable.insert("web_notify", record);
			return true;
		} catch (SQLException e) {
			logger.error("发送站内通知错误[{}][{}].", e.getMessage(),
					e.getClass().getSimpleName());
			return false;
		}
	}

	/**
	 * 发送一封电子邮件
	 */
	private static void sendNotifyMail(int level, String message) {
		(new Thread(new NotifyMailRunnable(level, message))).start();
	}

	static public boolean info(String message) {
		return notify(1, message);
	}

	static public boolean warn(String message) {
		return notify(2, message);
	}

	static public boolean error(String message) {
		return notify(3, message);
	}

	static public boolean fatal(String message) {
		return notify(4, message);
	}

}


/**
 * 发送通知邮件，在单独的线程中运行以避免阻塞
 */
class NotifyMailRunnable implements Runnable
{
	private static final Logger logger = LogManager.getLogger();

	private int level;
	private String message;

	public NotifyMailRunnable(int level, String message) {
		this.level = level;
		this.message = message;
	}

	@Override
	public void run() {
		JdbcTable table = JdbcTable.listAll_NE("web_email");
		if (table == null || table.getRecordCount() == 0) {
			logger.warn("查询系统通知邮件配置错误...");
			return;
		}
		JdbcRecord record = table.getRecord(0);
		if (!record.getBoolean("notify_mail")) {
			logger.debug("系统通知邮件被关闭，不用发送通知邮件.");
			return;
		}
		if (record.getInteger("notify_level") > level) {
			logger.debug("当前通知级别[{}]小于系统配置[{}]，不用发送通知邮件.",
					level, record.getInteger("notify_level"));
			return;
		}
		Map<String, String> recips =
				this.getNotifyRecips(record.getString("notify_recips"));
		if (recips.size() == 0) {
			logger.warn("没有配置系统通知收件人地址，不能发送邮件.");
			return;
		}
		String text = this.getNotifyText(this.level, this.message);
		MailSender sender = MailSender.getInstance();
		if (!sender.send("系统通知", text, recips)) {
			logger.error("发送系统通知邮件失败.");
		}
	}

	/**
	 * 解析收件人地址
	 */
	private Map<String, String> getNotifyRecips(String recips) {
		if (recips == null || recips.trim().isEmpty()) {
			logger.warn("没有配置系统通知收件人地址，发送邮件失败.");
			return null;
		}
		Map<String, String> retmap = new HashMap<>();
		for (String recip : recips.split(";")) {
			if (recip.trim().isEmpty()) {
				continue;
			}
			String[] address = recip.split(",");
			if (address.length == 1) {
				retmap.put(address[0].trim(), address[0].trim());
			} else {
				retmap.put(address[1].trim(), address[0].trim());
			}
		}
		return retmap;
	}

	/**
	 * 邮件正文
	 */
	private String getNotifyText(int level, String message) {
		SimpleDateFormat fmtter =
				new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String time = fmtter.format(new Date());

		StringBuilder builder = new StringBuilder();

		if (level >= 3) {
			builder.append("<p style='color:red;'>");
		} else {
			builder.append("<p>");
		}
		builder.append(message).append("</p>");

		builder.append("<ul>");
		builder.append("<li>来源：")
			.append(Runtime.getNotifySender()).append("</li>");
		builder.append("<li>级别：")
			.append(this.getLevelStr(level)).append("</li>");
		builder.append("<li>时间：").append(time).append("</li>");
		builder.append("</ul>");

		builder.append("<p style='color:grey;'>")
			.append("本邮件由系统自动发出，无需回复.</p>");
		return builder.toString();
	}

	/**
	 * 消息级别文字
	 */
	private String getLevelStr(int level) {
		switch (level) {
		case 1:
			return "1-通知";
		case 2:
			return "2-警告";
		case 3:
			return "3-错误";
		case 4:
			return "4-严重";
		default:
			return String.format("%d-未知", level);
		}
	}
}
